Skip to content

feat(ui): ship the new tab-bar UI to everyone - #613

Merged
bmc08gt merged 2 commits into
mainfrom
chore/ship-new-ui
Aug 20, 2026
Merged

feat(ui): ship the new tab-bar UI to everyone#613
bmc08gt merged 2 commits into
mainfrom
chore/ship-new-ui

Conversation

@bmc08gt

@bmc08gt bmc08gt commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

Flips BetaFlags.Option.newUI to a new .shipped availability tier and makes hasEnabled(_:) report .shipped options as on for everyone.

Why a new tier rather than deleting the flag

.shipped needs no call-site edits and no Settings-screen edits — both beta-flag screens already filter by availability (.developer / .publicBeta), so the row disappears on its own. It also means --beta-flags= can no longer switch the new UI off, and any previously stored opt-out is inert.

The flag itself, the 13 branch sites, the orphaned v1 chrome (ScanTopBar, ScanBottomBar, ScanScreen.isEmbedded), and the dead includingDollars: parameter chain come out in a follow-up.

UI tests

The v1 scanner chrome the XCUITest suite navigated through is now unreachable: the Settings button, the Cash give button, and the scan-* bottom-bar tabs. Those flows still exist but are entered differently, so the affected tests are skipped behind a shared skipPendingTabBarRewrite(_:) marker rather than rewritten blind — each skip names the route that moved, and .claude/plans/2026-08-20-ui-test-tab-bar-rewrite.md maps every old affordance to its replacement.

Two are repaired outright:

  • assertMainScreenReached() now looks for the Wallet tab — the launch tab, labelled by both the native and legacy tab bars. This keeps every wallet-rooted test running unchanged.
  • ForceLogoutSmokeTests asserted the Cash button was absent, which is now vacuously true. It asserts on the Wallet tab instead.

Adds a `.shipped` availability tier to `BetaFlags` and moves `.newUI` onto
it. A shipped option reports on from `hasEnabled(_:)` regardless of what is
stored, and neither Settings surface lists it — both already filter to
`.developer` / `.publicBeta`, so the toggle disappears without either screen
changing and no user can opt back out.

The flag and its branches stay in place; tearing them out of the call sites
is a follow-up.
Shipping the tab-bar UI to everyone retires the v1 scanner chrome the XCUITest
suite navigated through: the Settings button, the Cash give button, and the
scan-* bottom-bar tabs. Those flows still exist but are reached differently
now, so each affected test needs a rewrite verified on a simulator rather than
a selector swap.

Skip them through a shared `skipPendingTabBarRewrite(_:)` marker — greppable,
and each call site says which route moved. `.claude/plans/2026-08-20-ui-test-tab-bar-rewrite.md`
maps every old affordance to its replacement.

Two tests are repaired outright instead:

- `assertMainScreenReached()` now looks for the Wallet tab, the launch tab,
  which both the native and legacy tab bars label. That keeps the wallet-rooted
  tests running unchanged.
- `ForceLogoutSmokeTests` asserted on the Cash button, which no longer exists
  anywhere — so the assertion passed vacuously. Point it at the Wallet tab.
@bmc08gt
bmc08gt merged commit 4c677df into main Aug 20, 2026
@bmc08gt
bmc08gt deleted the chore/ship-new-ui branch August 20, 2026 20:38
bmc08gt added a commit that referenced this pull request Aug 26, 2026
The tab-bar UI shipped to everyone in #613, so `BetaFlags.Option.newUI`
had no readers left that could return false. Collapse every branch it
gated and delete the v1 surfaces it was the last route to.

Deleted: `BalanceScreen`, `ScanTopBar`/`ScanBottomBar`, the Currency Sell
flow (Convert replaces it and calls the same `Session.sell` machinery
underneath), `CurrencyInfoHeaderSection`/`CurrencyInfoFooter`, and
`CurrencyCreationPromoCard`.

Extracted rather than dropped: `ExchangedBalance` and `BalanceHeaderButton`
out of `BalanceScreen`, and `RootSheetHost` out of `ScanScreen`.

Router: `Stack.isTabHosted` replaces the runtime-registered
`AppRouter.tabStacks` set. The old set was published by `HomeTabView`'s
`onAppear`, so a deep link arriving before that view appeared fell through
to the sheet lookup and was dropped — `.balance` has no sheet of its own.
Making it a static fact on the stack fixes the cold-start case, and
`AppRouterCrossStackTests` pins it against `HomeTab.pushStack`.

`Availability` stays as-is; it is the mechanism for the next rollout, not
part of this flag.

Also picks up three symbols stranded by the deletions: `Session.canUseTips`
(body was `true`), `Image.Symbol.hamburger` with its imageset, and the
wallet leg of the token-info funnel. The last one is rewired rather than
removed — the tab-bar wallet expands the card in place instead of pushing
a screen, so `WalletScreen` now emits `openedFromWallet` on tap and
`openedFromDeeplink` on a deep-linked open.
bmc08gt added a commit that referenced this pull request Aug 26, 2026
The tab-bar UI shipped to everyone in #613, so `BetaFlags.Option.newUI`
had no readers left that could return false. Collapse every branch it
gated and delete the v1 surfaces it was the last route to.

Deleted: `BalanceScreen`, `ScanTopBar`/`ScanBottomBar`, the Currency Sell
flow (Convert replaces it and calls the same `Session.sell` machinery
underneath), `CurrencyInfoHeaderSection`/`CurrencyInfoFooter`, and
`CurrencyCreationPromoCard`.

Extracted rather than dropped: `ExchangedBalance` and `BalanceHeaderButton`
out of `BalanceScreen`, and `RootSheetHost` out of `ScanScreen`.

Router: `Stack.isTabHosted` replaces the runtime-registered
`AppRouter.tabStacks` set. The old set was published by `HomeTabView`'s
`onAppear`, so a deep link arriving before that view appeared fell through
to the sheet lookup and was dropped — `.balance` has no sheet of its own.
Making it a static fact on the stack fixes the cold-start case, and
`AppRouterCrossStackTests` pins it against `HomeTab.pushStack`.

`Availability` stays as-is; it is the mechanism for the next rollout, not
part of this flag.

Also picks up three symbols stranded by the deletions: `Session.canUseTips`
(body was `true`), `Image.Symbol.hamburger` with its imageset, and the
wallet leg of the token-info funnel. The last one is rewired rather than
removed — the tab-bar wallet expands the card in place instead of pushing
a screen, so `WalletScreen` now emits `openedFromWallet` on tap and
`openedFromDeeplink` on a deep-linked open.
bmc08gt added a commit that referenced this pull request Aug 26, 2026
The tab-bar UI shipped to everyone in #613, so `BetaFlags.Option.newUI`
had no readers left that could return false. Collapse every branch it
gated and delete the v1 surfaces it was the last route to.

Deleted: `BalanceScreen`, `ScanTopBar`/`ScanBottomBar`, the Currency Sell
flow (Convert replaces it and calls the same `Session.sell` machinery
underneath), `CurrencyInfoHeaderSection`/`CurrencyInfoFooter`, and
`CurrencyCreationPromoCard`.

Extracted rather than dropped: `ExchangedBalance` and `BalanceHeaderButton`
out of `BalanceScreen`, and `RootSheetHost` out of `ScanScreen`.

Router: `Stack.isTabHosted` replaces the runtime-registered
`AppRouter.tabStacks` set. The old set was published by `HomeTabView`'s
`onAppear`, so a deep link arriving before that view appeared fell through
to the sheet lookup and was dropped — `.balance` has no sheet of its own.
Making it a static fact on the stack fixes the cold-start case, and
`AppRouterCrossStackTests` pins it against `HomeTab.pushStack`.

`Availability` stays as-is; it is the mechanism for the next rollout, not
part of this flag.

Also picks up three symbols stranded by the deletions: `Session.canUseTips`
(body was `true`), `Image.Symbol.hamburger` with its imageset, and the
wallet leg of the token-info funnel. The last one is rewired rather than
removed — the tab-bar wallet expands the card in place instead of pushing
a screen, so `WalletScreen` now emits `openedFromWallet` on tap and
`openedFromDeeplink` on a deep-linked open.

Deleting the sell flow also removed the only `swapType: .sell` call site,
so `SwapType` loses the case and the arms it fed in title, subtitle,
navigationTitle, and trackTransaction. Convert keeps reporting through
`Analytics.tokenSell` — it still disposes of the source token.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant